﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.Entities.Providers
{
    public partial class PartitionEditor : Form, IComponentEditor 
    {
        private object _ActivityNode;
        private PartitionComponent _PartitionComponent;

        public PartitionEditor()
        {
            InitializeComponent();
        }

        private void PartitionEditor_Load(object sender, EventArgs e)
        {
            this.cbo_PartitionMethod.Items.Clear();
            for(int i=0;i<=2;i++)
            {
                PartitionMethod method = (PartitionMethod) i;
                this.cbo_PartitionMethod.Items.Add(method.ToString());
            }
        }

        #region IComponentEditor Members

        public event UpdateComponentSettings UpdateComponentSettingEvent;

        public object OwnerActivityNode
        {
            get { return _ActivityNode; }
            set { _ActivityNode = value; }
        }

        public Type WorkflowComponentType
        {
            get { return typeof (PartitionComponent); }
        }

        public void LoadSettings(GlobalVariable[] globalVars, WorkflowComponentBase[] fromComponents,
                                 object activityNode, WorkflowComponentBase wfComponent)
        {
            this._ActivityNode = activityNode;
            this._PartitionComponent = (PartitionComponent) wfComponent;

            // providers
            
            {
                this.rd_DbSource.Checked = true;
                this.cbo_DbProvider.SelectedIndex = 0;
                if (this._PartitionComponent.DbProvider == DataProviderType.Oracle)
                    this.cbo_DbProvider.SelectedIndex = 1;
                this.txt_ConnStr.Text = this._PartitionComponent.ConnStr;
                this.rt_SQL.Text = this._PartitionComponent.SelectSql;
            }

            // attributes
            this.cbo_PartitionAttributes.Items.Clear();
            this.cbo_IdAttribute.Items.Clear();
            if(this._PartitionComponent!=null && 
                !string.IsNullOrEmpty(this._PartitionComponent.ConnStr) && 
                !string.IsNullOrEmpty(this._PartitionComponent.SelectSql))
            {
                TableColumn[] cols = DbUtil.GetTableColumns(this._PartitionComponent.DbProvider,
                                                            this._PartitionComponent.ConnStr,
                                                            this._PartitionComponent.SelectSql);
                if(cols !=null && cols.Length>0)
                {
                    foreach (TableColumn col in cols)
                    {
                        this.cbo_PartitionAttributes.Items.Add(col.ColumnName);
                        this.cbo_IdAttribute.Items.Add(col.ColumnName);
                    }    
                }
            }
            if(this.cbo_IdAttribute.Items.Count>0 && !string.IsNullOrEmpty(this._PartitionComponent.IdAttributeName))
            {
                for(int i=0;i<this.cbo_IdAttribute.Items.Count;i++)
                {
                    if(this.cbo_IdAttribute.Items[i].ToString()==this._PartitionComponent.IdAttributeName)
                    {
                        this.cbo_IdAttribute.SelectedIndex = i;
                        break;
                    }
                }
            }
            this.txt_EntityCategory.Text = this._PartitionComponent.EntityCategory;

            this.dv_PartitionAttributes.Rows.Clear();
            if(this._PartitionComponent.AttrPartitions !=null && this._PartitionComponent.AttrPartitions.Count>0)
            {
                foreach(AttributePartition attrPartition in this._PartitionComponent.AttrPartitions)
                {
                    DataGridViewRow dr = new DataGridViewRow();
                    DataGridViewTextBoxCell cellAttName = new DataGridViewTextBoxCell();
                    cellAttName.Value = attrPartition.AttributeName;
                    dr.Cells.Add(cellAttName);

                    DataGridViewComboBoxCell cellMethod = new DataGridViewComboBoxCell();
                    cellMethod.Items.Add(PartitionMethod.Range.ToString());
                    cellMethod.Items.Add(PartitionMethod.Percent.ToString());
                    cellMethod.Items.Add(PartitionMethod.Distinct.ToString());
                    cellMethod.Value = attrPartition.Method.ToString();
                    dr.Cells.Add(cellMethod);

                    DataGridViewTextBoxCell cellBinSize = new DataGridViewTextBoxCell();
                    cellBinSize.Value = attrPartition.BinSize;
                    dr.Cells.Add(cellBinSize);

                    this.dv_PartitionAttributes.Rows.Add(dr);
                }

                this.num_MinCountPerPartition.Value = this._PartitionComponent.MinCountPerPartition;

                this.txt_ResultFilePath.Text = this._PartitionComponent.PartitionResultFilePath;
            }
        }

        public void SaveSettings()
        {
            string idAttrName = this.cbo_IdAttribute.Text;
            string entityCategory = this.txt_EntityCategory.Text;

            // provider 
            this._PartitionComponent.DbProvider = DataProviderType.MSSQL;
            if (this.cbo_DbProvider.SelectedIndex == 1)
                this._PartitionComponent.DbProvider = DataProviderType.Oracle;
            this._PartitionComponent.ConnStr = this.txt_ConnStr.Text;
            this._PartitionComponent.SelectSql = this.rt_SQL.Text;

            // meta data
            this._PartitionComponent.IdAttributeName = idAttrName;
            this._PartitionComponent.EntityCategory = entityCategory;

            // partitions
            this._PartitionComponent.AttrPartitions = new List<AttributePartition>();
            foreach (DataGridViewRow dr in this.dv_PartitionAttributes.Rows)
            {
                if (!dr.IsNewRow && dr.Cells[0].Value != null)
                {
                    string attrName = (string) dr.Cells[0].Value;
                    PartitionMethod method = PartitionMethod.Percent;
                    if (dr.Cells[1].Value.ToString() == PartitionMethod.Range.ToString())
                        method = PartitionMethod.Range;
                    else if (dr.Cells[1].Value.ToString() == PartitionMethod.Distinct.ToString())
                        method = PartitionMethod.Distinct;
                    double binSize = double.Parse(dr.Cells[2].Value.ToString());
                    AttributePartition attrPartition = new AttributePartition();
                    attrPartition.AttributeName = attrName;
                    attrPartition.Method = method;
                    attrPartition.BinSize = binSize;
                    this._PartitionComponent.AttrPartitions.Add(attrPartition);
                }
            }

            this._PartitionComponent.MinCountPerPartition = (int) this.num_MinCountPerPartition.Value;

            this._PartitionComponent.PartitionResultFilePath = this.txt_ResultFilePath.Text;
        }

        public TestResult Test()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region attributes from provider
        private List<AttributeMetaData> GetAttributeMetaDatasFromProvider(EntityProvider provider)
        {
            List<AttributeMetaData> attrMetaDatas = new List<AttributeMetaData>();
            
            if (provider.MetaData != null)
                attrMetaDatas = provider.MetaData.Attributes;
            return attrMetaDatas;
        }

        private void btn_BrowseDataSource_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "Entity provider files(*.xml)|*.xml|All files(*.*)|*.*";
            if(dlg.ShowDialog()==DialogResult.OK)
            {
                this.txt_EntityProviderFilePath.Text = dlg.FileName;
                this.cbo_IdAttribute.Items.Clear();
                this.cbo_PartitionAttributes.Items.Clear();
                EntityProvider provider = new EntityProvider(
                    this.txt_EntityProviderFilePath.Text,
                    "", this.txt_EntityCategory.Text);
                List<AttributeMetaData> attrMetaDatas = this.GetAttributeMetaDatasFromProvider(provider);
                if(attrMetaDatas !=null && attrMetaDatas.Count>0)
                {
                    foreach(AttributeMetaData attrMetaData in attrMetaDatas)
                    {
                        this.cbo_IdAttribute.Items.Add(attrMetaData.AttributeName);
                        this.cbo_PartitionAttributes.Items.Add(attrMetaData.AttributeName);
                    }
                }
            }
        }

        private void btn_Update_Click(object sender, EventArgs e)
        {
            if(!string.IsNullOrEmpty(this.txt_ConnStr.Text) && 
                !string.IsNullOrEmpty(this.rt_SQL.Text))
            {
                DataProviderType dbProvider = DataProviderType.MSSQL;
                if (this.cbo_DbProvider.SelectedIndex == 1)
                    dbProvider = DataProviderType.Oracle;
                EntityProvider provider = new EntityProvider(
                    dbProvider, this.txt_ConnStr.Text, this.rt_SQL.Text,
                    this.cbo_IdAttribute.Text, this.txt_EntityCategory.Text);
                this.cbo_IdAttribute.Items.Clear();
                this.cbo_PartitionAttributes.Items.Clear();
                List<AttributeMetaData> attrMetaDatas = this.GetAttributeMetaDatasFromProvider(provider);
                if (attrMetaDatas != null && attrMetaDatas.Count > 0)
                {
                    foreach (AttributeMetaData attrMetaData in attrMetaDatas)
                    {
                        this.cbo_IdAttribute.Items.Add(attrMetaData.AttributeName);
                        this.cbo_PartitionAttributes.Items.Add(attrMetaData.AttributeName);
                    }
                }
            }
        }

        #region source type switch
        private void rd_FileSource_CheckedChanged(object sender, EventArgs e)
        {
            if (this.rd_FileSource.Checked)
            {
                this.txt_EntityProviderFilePath.Enabled = true;
                this.btn_BrowseDataSource.Enabled = true;

                this.cbo_DbProvider.Enabled = false;
                this.txt_ConnStr.Enabled = false;
                this.rt_SQL.Enabled = false;
            }
            else
            {
                this.txt_EntityProviderFilePath.Enabled = false;
                this.btn_BrowseDataSource.Enabled = false;

                this.cbo_DbProvider.Enabled = true;
                this.txt_ConnStr.Enabled = true;
                this.rt_SQL.Enabled = true;
            }
        }

        private void rd_DbSource_CheckedChanged(object sender, EventArgs e)
        {
            if (this.rd_FileSource.Checked)
            {
                this.txt_EntityProviderFilePath.Enabled = true;
                this.btn_BrowseDataSource.Enabled = true;

                this.cbo_DbProvider.Enabled = false;
                this.txt_ConnStr.Enabled = false;
                this.rt_SQL.Enabled = false;
            }
            else
            {
                this.txt_EntityProviderFilePath.Enabled = false;
                this.btn_BrowseDataSource.Enabled = false;

                this.cbo_DbProvider.Enabled = true;
                this.txt_ConnStr.Enabled = true;
                this.rt_SQL.Enabled = true;
            }
        }
        #endregion

        #region src provider
        private void txt_EntityProviderFilePath_TextChanged(object sender, EventArgs e)
        {
            if(this.rd_FileSource.Checked && string.IsNullOrEmpty(this.txt_EntityProviderFilePath.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else if(this.rd_DbSource.Checked && string.IsNullOrEmpty(this.txt_ConnStr.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else if(this.rd_DbSource.Checked && string.IsNullOrEmpty(this.rt_SQL.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else
            {
                this.btn_OK.Enabled = true;
            }
        }

        private void txt_ConnStr_TextChanged(object sender, EventArgs e)
        {
            if (this.rd_FileSource.Checked && string.IsNullOrEmpty(this.txt_EntityProviderFilePath.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else if (this.rd_DbSource.Checked && string.IsNullOrEmpty(this.txt_ConnStr.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else if (this.rd_DbSource.Checked && string.IsNullOrEmpty(this.rt_SQL.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else
            {
                this.btn_OK.Enabled = true;
            }
        }

        private void rt_SQL_TextChanged(object sender, EventArgs e)
        {
            if (this.rd_FileSource.Checked && string.IsNullOrEmpty(this.txt_EntityProviderFilePath.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else if (this.rd_DbSource.Checked && string.IsNullOrEmpty(this.txt_ConnStr.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else if (this.rd_DbSource.Checked && string.IsNullOrEmpty(this.rt_SQL.Text))
            {
                this.btn_OK.Enabled = false;
            }
            else
            {
                this.btn_OK.Enabled = true;
            }
        }

        #endregion
        #endregion

        #region partition

        private void btn_AddPartitionAttribute_Click(object sender, EventArgs e)
        {
            if(this.cbo_PartitionAttributes.SelectedIndex>=0 && this.cbo_PartitionMethod.SelectedIndex>=0)
            {
                PartitionMethod method = (PartitionMethod) this.cbo_PartitionMethod.SelectedIndex;
                string attrName = this.cbo_PartitionAttributes.SelectedItem.ToString();
                double binSize = (double)this.num_PartitionBin.Value;

                DataGridViewRow dr = new DataGridViewRow();
                DataGridViewTextBoxCell cellAttrName = new DataGridViewTextBoxCell();
                cellAttrName.Value = attrName;
                dr.Cells.Add(cellAttrName);

                DataGridViewComboBoxCell cellMethod = new DataGridViewComboBoxCell();
                cellMethod.Items.Add(PartitionMethod.Range.ToString());
                cellMethod.Items.Add(PartitionMethod.Percent.ToString());
                cellMethod.Items.Add(PartitionMethod.Distinct.ToString());
                cellMethod.Value = method.ToString();
                dr.Cells.Add(cellMethod);

                DataGridViewTextBoxCell cellBinSize = new DataGridViewTextBoxCell();
                cellBinSize.Value = binSize;
                dr.Cells.Add(cellBinSize);

                this.dv_PartitionAttributes.Rows.Add(dr);
            }
        }

        #endregion

        private void btn_SaveOutput_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "Partition result files(*.xml)|*.xml|All files(*.*)|*.*";
            if(dlg.ShowDialog()==DialogResult.OK)
            {
                this.txt_ResultFilePath.Text = dlg.FileName;
            }
        }

        private void btn_OK_Click(object sender, EventArgs e)
        {
            this.SaveSettings();

            if(this.UpdateComponentSettingEvent !=null)
            {
                this.UpdateComponentSettingEvent(this._ActivityNode, this._PartitionComponent);
            }

            this.Close();
        }

        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void cbo_PartitionMethod_SelectedIndexChanged(object sender, EventArgs e)
        {
            PartitionMethod method = (PartitionMethod)this.cbo_PartitionMethod.SelectedIndex;
            if (method == PartitionMethod.Range)
            {
                this.lbl_Pct.Visible = false;
                this.num_PartitionBin.Visible = true;
            }
            else if(method==PartitionMethod.Percent)
            {
                this.lbl_Pct.Visible = true;
                this.num_PartitionBin.Visible = true;
            }
            else if(method==PartitionMethod.Distinct)
            {
                this.lbl_Pct.Visible = false;
                this.num_PartitionBin.Value = 1;
                this.num_PartitionBin.Visible = false;
            }
        }


    }
}
